package cn.tramy.pinxian.common.util.func


import cn.tramy.pinxian.common.exception.CommonException
import java.util.*

/**
 * Created  on 16/8/29.
 */
class LoadConditionThenFunc<T>(private val loadFunc: () -> T?) : CommonFunc {
    private val consumers = ArrayList<(data: T?) -> Unit>()
    private var conditionalFunc: ((data: T?) -> Boolean)? = null

    private var exceptionFunc: (() -> Throwable)? = null

    fun ifTrue(booleanSupplier: (data: T?) -> Boolean): LoadConditionThenFunc<T> {
//        Objects.requireNonNull(booleanSupplier)
        //        ExecuteTool.conditionalException(() -> Objects.nonNull(this.conditionalFunc), () -> CommonException.invalidOperation());
        this.conditionalFunc = booleanSupplier
        return this
    }

    fun ifNonNull(): LoadConditionThenFunc<T> {
        return ifTrue { Objects.nonNull(it) }
    }

    fun ifNull(): LoadConditionThenFunc<T> {
        return ifTrue { Objects.isNull(it) }
    }


    fun invalidOperationException(): LoadConditionThenFunc<T> {
        exception { CommonException.invalidOperation() }
        return this
    }

    fun exception(exceptionFunc: () -> Throwable): LoadConditionThenFunc<T> {
//        Objects.requireNonNull(exceptionFunc)
//        ExecuteTool.conditionalException({ Objects.nonNull(this.exceptionFunc) }, { CommonException.invalidOperation() })
        this.exceptionFunc = exceptionFunc
        return this
    }


    fun then(processFunc: (data: T?) -> Unit): LoadConditionThenFunc<T> {
        Objects.requireNonNull(processFunc)
        this.consumers.add(processFunc)
        return this
    }

    override fun execute() {
        val obj = this.loadFunc()

        conditionalFunc?.let {
            if (!it(obj)) {
                exceptionFunc?.let { throw it() }
            }
        }

        this.consumers.forEach { it(obj) }


//        if (Objects.isNull(conditionalFunc) || conditionalFunc(obj!!)) {
//            //            ExecuteTool.ifTrue(() -> Objects.isNull(obj)).exception(() -> CommonException.NPE()).execute();
//            if (Objects.nonNull(consumers)) {
//                consumers.forEach { tConsumer -> tConsumer.accept(obj) }
//            }
//        } else {
//            if (Objects.nonNull(exceptionFunc)) {
//                throw this.exceptionFunc()
//            }
//        }


    }
}
